#include "GamePlayState.h"
//SGD Wrappers
#include "../../SGD_Wrappers/CSGD_Direct3D.h"
#include "../../SGD_Wrappers/CSGD_DirectInput.h"
#include "../../SGD_Wrappers/CSGD_TextureManager.h"
#include "../../SGD_Wrappers/CSGD_XAudio2.h"
#include "../../SGD_Wrappers/SGD_String.h"
#include "../../SGD_Wrappers/CSGD_EventSystem.h"
#include "../Game.h"
#include "PauseState.h"
#include "MainMenuState.h"
#include "../../source/GameObjects/Player/Player.h"
#include "../SoundSystem/SoundSystem.h"
#include "../CreateLightPrimBullet.h"
#include "../GameObjects/Gun/LightningPrimary.h"
#include "../GameObjects/Entity.h"
#include "../GameObjects/Enemies/Peon.h"
#include "../DestroyEntityMessage.h"
#include "../CreateFirePrim.h"
#include "../GameObjects/Gun/FirePrimary.h"
#include "../GameObjects/Items/Key.h"
#include <iostream>
using namespace std;
#include <fstream>
#include "../GameObjects/Items/PowerUps.h"
#include "../ElectricAreaEffect.h"
#include "../ElectricMessage.h"
#include "../Tiles/TileManager.h"
#include "../Tiles/Tile.h"
#include "../Game.h"

CGamePlayState::CGamePlayState()
{
	m_pES->GetInstance()->RegisterClient("CHANGE_COLOR", this);
	m_nColor = 255;

	
	m_pSS = SoundSystem::GetInstance();
	//m_pSS->playSound("DST-AngryRobotIII",true);
}

CGamePlayState::~CGamePlayState()
{
	//delete m_pPlayer;
	//delete m_pPeon;
	//delete m_pPeon1;
	//delete m_pPeon2;
}

CGamePlayState*	CGamePlayState::GetInstance( void )
{
	//Store an instance in global memory
	static CGamePlayState s_Instance;

	//Return the instance
	return &s_Instance;
}

// IGameState Interface
void	CGamePlayState::Enter	( void )
{
	// Store the SGD Wrapper singletons
	m_pD3D	= CSGD_Direct3D::GetInstance();
	m_pDI	= CSGD_DirectInput::GetInstance();
	m_pTM	= CSGD_TextureManager::GetInstance();
	m_pXA	= CSGD_XAudio2::GetInstance();
	m_pES   = CSGD_EventSystem::GetInstance();
	m_pMS	= CSGD_MessageSystem::GetInstance();
	m_pOM	= CObjectManager::GetInstance();

	m_pMS->InitMessageSystem( &MessageProc );


	ifstream fin;
	
	fin.open("Settings.txt",ios_base::in);

	if(fin.good())
		{
			float fSound;
			int Window;
			fin >> fSound;
			SoundSystem::GetInstance()->SetVolume(fSound);
			fin.ignore(INT_MAX, '\n');
			fin >> Window;
			if(Window == 1)
				CGame::GetInstance()->SetWindow(true);
			else
				CGame::GetInstance()->SetWindow(false);
		}

	fin.close();
	m_pPlayer = new CPlayer;
	m_pPlayer->Init();
	m_pPeon = new CPeon;
	m_pPeon->Init();
	m_pPlayer->Load(m_nSaveToLoad);
	m_pPeon->SetTarget(m_pPlayer);
	std::string XMLLevel = "TileSets/TestXML.xml";
	CTileManager::GetInstance()->ReadLevel( XMLLevel );
	m_pPeon1 = new CPeon;
	m_pPeon1->Init();
	m_pPeon1->SetTarget(m_pPlayer);

	m_pPeon2 = new CPeon;
	m_pPeon2->Init();
	m_pPeon2->SetTarget(m_pPlayer);

	m_pPeon1->SetPosX(58);
	m_pPeon1->SetPosY(50);

	m_pPeon2->SetPosX(90);
	m_pPeon2->SetPosY(80);

	m_pOM->AddObject( m_pPlayer );
	m_pOM->AddObject(m_pPeon);
	m_pOM->AddObject( m_pPeon1 );
	m_pOM->AddObject( m_pPeon2 );

	//m_pPlayer->Release();
	//m_pPeon->Release();
	//m_pPeon1->Release();
	//m_pPeon2->Release();


	CPowerUps* shield = new CPowerUps();
	shield->SetPosX( 60 );
	shield->SetPosY( 80 );

	CKey* key = new CKey();
	key->SetPosX(500);
	key->SetPosY(500);

	m_pOM->AddObject(key);
	m_pOM->AddObject( shield );

	std::vector<CTile*> tiles = CTileManager::GetInstance()->RecieveEventLayer();

	for(unsigned int i = 0; i < tiles.size(); ++i)
	{
		if(tiles[i]->GetItemType() == 1)
		{
			shield->SetPosX(tiles[i]->GetWorldPosX());
			shield->SetPosY(tiles[i]->GetWorldPosY());
		}
		else if(tiles[i]->GetItemType() == 2)
		{
			key->SetPosX(tiles[i]->GetWorldPosX());
			key->SetPosY(tiles[i]->GetWorldPosY());
		}
	}

	shield->Release();
	key->Release();
}

void	CGamePlayState::Exit	( void )
{
	m_pSS->StopSounds();

	if(m_pPlayer != nullptr)
	{
		m_pPlayer->Save(m_nSaveToLoad);
		//m_pPlayer->Release();
		//m_pPlayer = nullptr;
	}
	// Shutdown the message system
	if( m_pMS != nullptr )
	{
		m_pMS->ShutdownMessageSystem();
		m_pMS = nullptr;
	}

	//Shutdown object manager
	if( m_pOM != nullptr )
	{
		m_pOM->RemoveAllObjects();
		CObjectManager::DeleteInstance();
		m_pOM = nullptr;
	}
	//delete m_pPlayer;
	//delete m_pPeon;
	

	CTileManager::GetInstance()->Shutdown();

	// Shutdown the message system
	if( m_pMS != nullptr )
	{
		m_pMS->ShutdownMessageSystem();
		m_pMS = nullptr;
	}

	//Shutdown object manager
	if( m_pOM != nullptr )
	{
		m_pOM->RemoveAllObjects();
		CObjectManager::DeleteInstance();
		m_pOM = nullptr;
	}

	if( m_pES != nullptr )
	{
		m_pES->ClearEvents();
		m_pES->ShutdownEventSystem();
		m_pES = nullptr;
	}


	//delete m_pPlayer;
	//delete m_pPeon;
	//delete m_pPeon1;
	//delete m_pPeon2;

	m_pPlayer->Release();
	m_pPeon->Release();
	m_pPeon1->Release();
	m_pPeon2->Release();

}

bool	CGamePlayState::Input	( void )
{
	if(m_pDI->KeyPressed(DIK_S)==true)
	{
		m_pSS->playSound("pickup1",false);
	}
	if( m_pDI->KeyPressed( DIK_E ) == true )
	{
		CGame::GetInstance()->ChangeState( CMainMenuState::GetInstance() );
	}


	if( m_pDI->KeyPressed( DIK_ESCAPE ) == true )
	{
		CGame::GetInstance()->AddState( CPauseState::GetInstance() );
	}

	return true;
}

void	CGamePlayState::Update	( float fElapsedTime )
{
	CTileManager::GetInstance( )->CheckCollsion( m_pPlayer );
	m_pSS->Update();
	
	m_pOM->UpdateAllObjects( fElapsedTime );
	
	m_pMS->ProcessMessages();

	m_pOM->CheckCollisions();
	m_pES->ProcessEvents();
}

void	CGamePlayState::Render	( void )
{
	CTileManager::GetInstance()->Render();
	//m_pD3D->DeviceBegin();
	m_pD3D->Clear( 0, m_nColor, 0 );
	m_pD3D->GetSprite()->Flush();
	m_pOM->RenderAllObjects();
	m_pD3D->GetSprite()->Flush();
}

void CGamePlayState::HandleEvent(CEvent* pEvent)
{
	if(pEvent->GetEventID() == "CHANGE_COLOR")
	{
		if(this == pEvent->GetDestination())
		{
			m_nColor = (int)pEvent->GetParam();
		}
	}
}


void CGamePlayState::MessageProc( IMessage* pMsg )
{
	CGamePlayState* self = CGamePlayState::GetInstance();

	switch( pMsg->GetMessageID() )
	{
	case Msg_LightPrimBullet:
		{
			CLightningPrimary* l = new CLightningPrimary();

			CreateLightPrimBullet* tempMsg = dynamic_cast<CreateLightPrimBullet*>(pMsg);

			CEntity* own = tempMsg->GetOwner();
			dynamic_cast<CLightningPrimary*>(l)->SetOwner( (CEntity*)own);
			dynamic_cast<CBullet*>(l)->SetWidth( 8 );
			dynamic_cast<CBullet*>(l)->SetHeight( 8 );	
			dynamic_cast<CBullet*>(l)->SetPosX(own->GetPosX() );
			dynamic_cast<CBullet*>(l)->SetPosY(own->GetPosY() );

			float fRotation;

			if( own->GetType() == 1 )
				fRotation = dynamic_cast<CPlayer*>(own)->GetRotation();
			else 
			{
				fRotation = dynamic_cast<CElectricAreaEffect*>(own)->GetAngle();
			}
			

			tVector2D vOrientation = { 0, 1 };		// default orientation

			vOrientation = Vector2DRotate( vOrientation, fRotation );

			vOrientation = vOrientation * 100;

			l->SetVelX( vOrientation.fX );
			l->SetVelY( vOrientation.fY );


			self->m_pOM->AddObject( l );
			l->Release();
			l = nullptr;


		}
		break;

	case Msg_CreateFirePrimBullet:
		{
			CFirePrimary* l = new CFirePrimary();

			CCreateFirePrim* tempMsg = dynamic_cast<CCreateFirePrim*>(pMsg);

			CPlayer* own = tempMsg->GetOwner();
			dynamic_cast<CFirePrimary*>(l)->SetOwner( (CEntity*)own);
			dynamic_cast<CBullet*>(l)->SetWidth( 8 );
			dynamic_cast<CBullet*>(l)->SetHeight( 8 );	
			dynamic_cast<CBullet*>(l)->SetPosX(own->GetPosX() );
			dynamic_cast<CBullet*>(l)->SetPosY(own->GetPosY() );

			float fRotation = own->GetRotation()-0.5f;

			tVector2D vOrientation = { 0, 1 };		// default orientation

			vOrientation = Vector2DRotate( vOrientation, fRotation );

			vOrientation = vOrientation * 100;

			l->SetVelX( vOrientation.fX );
			l->SetVelY( vOrientation.fY );
			l->SetRotation(fRotation);
			l->SetSide(0);
			l->SetDestination(own->GetMouseClick());
			self->m_pOM->AddObject( l );
			l->Release();
			l = nullptr;

			l = new CFirePrimary();

			tempMsg = dynamic_cast<CCreateFirePrim*>(pMsg);

			own = tempMsg->GetOwner();
			dynamic_cast<CFirePrimary*>(l)->SetOwner( (CEntity*)own);
			dynamic_cast<CBullet*>(l)->SetWidth( 8 );
			dynamic_cast<CBullet*>(l)->SetHeight( 8 );	
			dynamic_cast<CBullet*>(l)->SetPosX(own->GetPosX() );
			dynamic_cast<CBullet*>(l)->SetPosY(own->GetPosY() );

			fRotation = own->GetRotation();

			vOrientation.fX = 0;	
			vOrientation.fY = 1;

			vOrientation = Vector2DRotate( vOrientation, fRotation );

			vOrientation = vOrientation * 100;

			l->SetVelX( vOrientation.fX );
			l->SetVelY( vOrientation.fY );
			l->SetRotation(fRotation);
			l->SetSide(1);
			l->SetDestination(own->GetMouseClick());
			self->m_pOM->AddObject( l );
			l->Release();
			l = nullptr;

			l = new CFirePrimary();

			tempMsg = dynamic_cast<CCreateFirePrim*>(pMsg);

			own = tempMsg->GetOwner();
			dynamic_cast<CFirePrimary*>(l)->SetOwner( (CEntity*)own);
			dynamic_cast<CBullet*>(l)->SetWidth( 8 );
			dynamic_cast<CBullet*>(l)->SetHeight( 8 );	
			dynamic_cast<CBullet*>(l)->SetPosX(own->GetPosX() );
			dynamic_cast<CBullet*>(l)->SetPosY(own->GetPosY() );

			fRotation = own->GetRotation()+0.5f;

			vOrientation.fX = 0;	
			vOrientation.fY = 1;
			
			vOrientation = Vector2DRotate( vOrientation, fRotation );

			vOrientation = vOrientation * 100;

			l->SetVelX( vOrientation.fX );
			l->SetVelY( vOrientation.fY );
			l->SetDestination(own->GetMouseClick());
			l->SetRotation(fRotation);
			l->SetSide(2);
			self->m_pOM->AddObject( l );
			l->Release();
			l = nullptr;


		}
		break;

	case Msg_DestroyEntity:
		{
			CEntity* b = dynamic_cast<CDestroyEntityMessage*>(pMsg)->GetEntity();
			self->m_pOM->RemoveObject( b );
			b = nullptr;
		}
		break;
		
	case Msg_Electricity:
		{
			CElectricAreaEffect* e = new CElectricAreaEffect();

			ElectricMessage* tempMsg = dynamic_cast<ElectricMessage*>(pMsg);

		
			dynamic_cast<CElectricAreaEffect*>(e)->SetWidth( 40 );
			dynamic_cast<CElectricAreaEffect*>(e)->SetHeight( 40 );	
			dynamic_cast<CElectricAreaEffect*>(e)->SetPosX((float)(dynamic_cast<ElectricMessage*>(pMsg)->GetX()) );
			dynamic_cast<CElectricAreaEffect*>(e)->SetPosY((float)(dynamic_cast<ElectricMessage*>(pMsg)->GetY()) );

			


			self->m_pOM->AddObject( e );
			e->Release();
			e = nullptr;
		} 
		break;

}


	

}
